package com.chenfan.mcn.service.impl;

import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson.TypeReference;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.chenfan.mcn.clients.baseinfo.BaseDicts;
import com.chenfan.mcn.clients.baseinfo.BaseInfoClient;
import com.chenfan.mcn.config.UserVoContextHolder;
import com.chenfan.mcn.constant.DictTypeCst;
import com.chenfan.mcn.constant.McnConstant;
import com.chenfan.mcn.constant.NumberCst;
import com.chenfan.mcn.constant.SeparatorCst;
import com.chenfan.mcn.dao.StarPlatformInfoMapper;
import com.chenfan.mcn.dao.StarPlatformSettlementInfoMapper;
import com.chenfan.mcn.enums.LogBusinessTypeEnum;
import com.chenfan.mcn.enums.ImportExcelEnum;
import com.chenfan.mcn.event.EventPublisher;
import com.chenfan.mcn.event.OperateLogEvent;
import com.chenfan.mcn.exception.McnErrorCode;
import com.chenfan.mcn.extension.excel.ExcelUtils;
import com.chenfan.mcn.model.StarPlatformInfo;
import com.chenfan.mcn.model.StarPlatformSettlementInfo;
import com.chenfan.mcn.model.dto.StarPlatformInfoInputDTO;
import com.chenfan.mcn.model.dto.StarPlatformInfoOutputDTO;
import com.chenfan.mcn.model.vo.StarPlatInfoVO;
import com.chenfan.mcn.model.vo.StarPlatSelectVO;
import com.chenfan.mcn.service.StarPlatformInfoService;
import com.chenfan.mcn.utils.BaseAssemblerUtil;
import com.chenfan.mcn.utils.BusinessAssert;
import com.chenfan.mcn.utils.CommonUtil;
import com.chenfan.mcn.utils.ValidatorUtil;
import com.google.common.collect.Lists;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletResponse;
import java.util.*;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

/**
 * @Author liuyang
 * @Date 2021/1/7
 * @Time 20:56
 * @Version V1.0
 **/
@Slf4j
@Service
public class StarPlatformInfoServiceImpl implements StarPlatformInfoService {

    @Autowired
    private StarPlatformInfoMapper starPlatformInfoMapper;

    @Autowired
    private StringRedisTemplate stringRedisTemplate;

    @Autowired
    private BaseInfoClient baseInfoClient;

    @Resource
    private StarPlatformSettlementInfoMapper starPlatformSettlementInfoMapper;


    @Override
    public List<StarPlatInfoVO> getByName(String starName) {
        List<StarPlatInfoVO> platInfoVOList = new ArrayList<>();
        if (StringUtils.isNotBlank(starName)) {
            platInfoVOList = starPlatformInfoMapper.getByName(starName);
        }
        return platInfoVOList;
    }

    @Override
    public List<StarPlatInfoVO> getByIds(List<Long> ids) {
        return starPlatformInfoMapper.getByIds(ids);
    }

    @Override
    public StarPlatInfoVO getById(Long id) {
        return starPlatformInfoMapper.getById(id);
    }

    @Override
    public List<StarPlatInfoVO> getAll(Integer starType, Integer starStatus, Integer platformStatus, String platformId, Long starId) {
        return starPlatformInfoMapper.getAll(starType, starStatus, platformStatus, platformId, starId);
    }

    @Override
    public void updatePlatformStatus(Long id, Integer starStatus) {
        starPlatformInfoMapper.updateByNoStrategy(Wrappers.lambdaUpdate(StarPlatformInfo.class)
                .set(StarPlatformInfo::getPlatformStatus, starStatus)
                .eq(StarPlatformInfo::getId, id));
        if (Objects.equals(starStatus, NumberCst.ONE)) {
            //如果是禁用 联动禁用关联的所用结算信息
            starPlatformSettlementInfoMapper.updateByNoStrategy(Wrappers.lambdaUpdate(StarPlatformSettlementInfo.class)
                    .set(StarPlatformSettlementInfo::getStatus, NumberCst.ZERO)
                    .eq(StarPlatformSettlementInfo::getStarPlatformInfoId, id));
        }
    }

    @Override
    public List<StarPlatSelectVO> getAllStarPlatSelect(Long tenantId) {
        return starPlatformInfoMapper.getAllStarPlatSelect(tenantId);
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public String importUpdatePlafromExcel(List<StarPlatformInfoInputDTO> inputList) {
        //1、校验参数格式
        List<StarPlatformInfoOutputDTO> outputList = inputList.stream().map(e -> {
            StarPlatformInfoOutputDTO outputDTO = new StarPlatformInfoOutputDTO();
            BeanUtils.copyProperties(e, outputDTO);
            outputDTO.setFailedReason(ValidatorUtil.getJointValidateResult(outputDTO, SeparatorCst.LINE_BREAK));

            return outputDTO;
        }).collect(Collectors.toList());
        //2、校验唯一性
        List<String> repeatedVouchers = outputList.stream().filter(e -> StringUtils.isNotBlank(e.getPlatformName()) && StringUtils.isNotBlank(e.getPlatNickName()))
                .collect(Collectors.groupingBy(e -> StringUtils.joinWith(SeparatorCst.PLUS, e.getPlatformName(), e.getPlatNickName()), Collectors.counting()))
                .entrySet().stream().filter(e -> e.getValue().longValue() > 1L).map(Map.Entry::getKey).collect(Collectors.toList());
        outputList.forEach(e -> {
            if (StringUtils.isNotBlank(e.getPlatformName()) && StringUtils.isNotBlank(e.getPlatNickName())
                    && repeatedVouchers.contains(StringUtils.joinWith(SeparatorCst.PLUS, e.getPlatformName(), e.getPlatNickName()))) {
                e.setFailedReason(CommonUtil.joinWith(SeparatorCst.LINE_BREAK, e.getFailedReason(), "文件所在平台+平台昵称不唯一，请检查后重试！"));
            }
        });
        //3、校验系统数据匹配校验
        Map<String, String> platformMap = CommonUtil.defaultList(baseInfoClient.getDictList(DictTypeCst.ACTIVE_PLATFORMS).getObj())
                .stream().filter(e -> !e.getDictsStatus().booleanValue()).collect(Collectors.toMap(BaseDicts::getDictsNameC, BaseDicts::getDictsCode));
        List<String> platNickNames = outputList.stream().map(StarPlatformInfoOutputDTO::getPlatNickName).filter(StringUtils::isNotBlank).distinct().collect(Collectors.toList());
        Map<String, List<StarPlatformInfo>> starPlatformInfoMap = CommonUtil.defaultList(
                starPlatformInfoMapper.selectList(Wrappers.lambdaQuery(StarPlatformInfo.class).eq(StarPlatformInfo::getIsDelete, NumberCst.ZERO)
                        .in(StarPlatformInfo::getPlatformId, platformMap.values())
                        .in(StarPlatformInfo::getPlatNickName, platNickNames)
                        .in(StarPlatformInfo::getPlatformStatus, NumberCst.ZERO)
                        .exists("select 1 from star_basic_data where id = star_id and is_delete = 0 and star_status = 0")
                )).stream().collect(Collectors.groupingBy(k -> StringUtils.joinWith(SeparatorCst.PLUS, k.getPlatformId(), k.getPlatNickName())));
        outputList.forEach(output -> {
            output.verifySysDataMatch(platformMap, starPlatformInfoMap, SeparatorCst.LINE_BREAK);
        });
        List<StarPlatformInfoOutputDTO> successList = outputList.stream().filter(e -> StringUtils.isBlank(e.getFailedReason())).collect(Collectors.toList());
        List<StarPlatformInfoOutputDTO> failedList = outputList.stream().filter(e -> StringUtils.isNotBlank(e.getFailedReason())).collect(Collectors.toList());
        if (CollectionUtils.isNotEmpty(successList)) {
            List<OperateLogEvent> eventList = new ArrayList<>(successList.size());
            List<StarPlatformInfo> updateList = successList.stream().map(e -> {
                StarPlatformInfo starPlatformInfo = e.getStarPlatformInfo();
                StarPlatformInfo updateStarPlatformInfo = new StarPlatformInfo();
                BeanUtils.copyProperties(starPlatformInfo, updateStarPlatformInfo);
                updateStarPlatformInfo.setPlatformStatus(e.getPlatformStatus());
                updateStarPlatformInfo.setIsAssessment(e.getIsAssessment());
                updateStarPlatformInfo.setPlatLinkUrl(e.getPlatLinkUrl());
                updateStarPlatformInfo.setStarPlatformId(e.getStarPlatformId());
                updateStarPlatformInfo.setUserId(e.getUserId());
                updateStarPlatformInfo.setFansQuantity(e.getFansQuantity());
                updateStarPlatformInfo.setGraphicReadingQuantity(e.getGraphicReadingQuantity());
                updateStarPlatformInfo.setInteractiveQuantity(e.getInteractiveQuantity());
                updateStarPlatformInfo.setVideoPlayQuantity(e.getVideoPlayQuantity());
                updateStarPlatformInfo.setVideoReadingQuantity(e.getVideoReadingQuantity());
                updateStarPlatformInfo.setDevidedRate(e.getDevidedRate());
                updateStarPlatformInfo.setIndividualResume(StringUtils.defaultString(e.getIndividualResume()));
                updateStarPlatformInfo.setRemark(StringUtils.defaultString(e.getRemark()));

                eventList.add(OperateLogEvent.builder().businessId(starPlatformInfo.getStarId())
                        .businessType(LogBusinessTypeEnum.STAR_PLATFORM_INFO)
                        .compare(starPlatformInfo, updateStarPlatformInfo)
                        .build());
                return updateStarPlatformInfo;
            }).collect(Collectors.toList());
            Lists.partition(updateList, McnConstant.MAX_INSERT_SIZE).forEach(subList -> {
                BaseAssemblerUtil.batchUpdateFill(subList, UserVoContextHolder.getUserVo());
                starPlatformInfoMapper.saveBatch(subList);
            });
            EventPublisher.post(eventList);
            updateList.clear();
            successList.clear();
        }
        if (CollectionUtils.isNotEmpty(failedList)) {
            return generateDownloadFiledId(failedList);
        }
        return null;
    }

    private String generateDownloadFiledId(List<StarPlatformInfoOutputDTO> outputList) {
        String fileId = ImportExcelEnum.UPDATE_STAR_PLATFORM_INFO.getFileId();
        stringRedisTemplate.opsForValue().set(McnConstant.CACHE_PRIFIX + fileId, JSONObject.toJSONString(outputList), 30, TimeUnit.MINUTES);
        return fileId;
    }

    @Override
    public void downloadUpdatePlafromFailedReason(HttpServletResponse response, String fileId) {
        BusinessAssert.isTrue(ImportExcelEnum.match(fileId, ImportExcelEnum.UPDATE_STAR_PLATFORM_INFO), McnErrorCode.EXPORT_FILE_ID_ILLEGAL);
        // 根据FileId判断导出类型
        String excelContent = CommonUtil.defaultIfEmpty(stringRedisTemplate.opsForValue().get(McnConstant.CACHE_PRIFIX + fileId));
        List<StarPlatformInfoOutputDTO> outputList = JSONObject.parseObject(excelContent, new TypeReference<List<StarPlatformInfoOutputDTO>>() {
        });
        BusinessAssert.notEmpty(outputList, McnErrorCode.EXPORT_HAS_NO_DATA);
        try {
            String title = "批量导入跟新红人平台信息失败原因";
            ExcelUtils.exportExcel(outputList, title, StarPlatformInfoOutputDTO.class, title + ".xlsx", response);
            stringRedisTemplate.delete(McnConstant.CACHE_PRIFIX + fileId);
        } catch (Exception e) {
            log.error(e.getMessage(), e);
        }
    }

    @Override
    public Integer getIsSystemAdmin(Long starPlatformId, List<Long> joinIds) {
        if (Objects.isNull(starPlatformId)) {
            return NumberCst.ZERO;
        }
        List<StarPlatformSettlementInfo> dataList = CommonUtil.defaultList(
                starPlatformSettlementInfoMapper.selectList(Wrappers.lambdaQuery(StarPlatformSettlementInfo.class)
                        .eq(StarPlatformSettlementInfo::getStarPlatformInfoId, starPlatformId)
                        .eq(StarPlatformSettlementInfo::getIsDelete, NumberCst.ZERO))
        ).stream().collect(Collectors.toList());
        if (CollectionUtils.isEmpty(dataList) | CollectionUtils.isEmpty(joinIds)) {
            return NumberCst.ZERO;
        }
        List<StarPlatformSettlementInfo> newDataList = dataList.stream().filter(e -> joinIds.contains(e.getId())).collect(Collectors.toList());
        StarPlatformSettlementInfo firstVo = newDataList.stream()
                .filter(e -> StringUtils.endsWithIgnoreCase(e.getCooperationContent(), McnConstant.COOPERATION_CONTENT_SUFFIX))
                .findFirst().orElse(null);
        if(Objects.isNull(firstVo) && CollectionUtils.isNotEmpty(newDataList)) {
            firstVo = newDataList.get(0);
        }
        return Objects.nonNull(firstVo) ? firstVo.getInSystemAdmin() : NumberCst.ZERO;
    }

    @Override
    public Integer getIsSystemAdmin(Long starPlatformId, String cooperationContent) {
        if (Objects.isNull(starPlatformId) || StringUtils.isBlank(cooperationContent)) {
            return NumberCst.ZERO;
        }
        StarPlatformSettlementInfo starPlatformSettlementInfo = starPlatformSettlementInfoMapper.selectOne(Wrappers.lambdaQuery(StarPlatformSettlementInfo.class)
                        .eq(StarPlatformSettlementInfo::getStarPlatformInfoId, starPlatformId)
                        .eq(StarPlatformSettlementInfo::getCooperationContent, cooperationContent)
                        .eq(StarPlatformSettlementInfo::getIsDelete, NumberCst.ZERO));
        BusinessAssert.notNull(starPlatformSettlementInfo, "该合作内容对应平台结算信息尚未维护！");
        return starPlatformSettlementInfo.getInSystemAdmin();
    }
}
